<?php

namespace App\Command;

use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use App\Common\Record;
use App\Entity\WinTrunkMonitorHour;
use App\Entity\WinTrunkMonitorDay;
use App\Entity\WinTrunkMonitorMonth;
use App\Entity\WinTrunkName;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Class ConnectRateCommand
 * @package App\Command
 */
class ConnectRateCommand extends ContainerAwareCommand
{
    /** @var LoggerInterface  */
    private $logger;

    private $container;

    protected function configure()
    {
        $this
            // the name of the command (the part after "bin/console")
            ->setName('command:statistics:trunk');
    }

    /**
     * ConnectRateCommand constructor.
     * @param LoggerInterface $logger
     * @param ContainerInterface $container
     */
    public function __construct(LoggerInterface $logger, ContainerInterface $container)
    {
        parent::__construct();
        $this->logger = $logger;
        $this->container = $container;
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $time = time();
        $hourTime = date('Y-m-d H', strtotime("-1 hour", $time));
        $dayTime = date("Y-m-d", strtotime("-1 hour", $time));
        $monthTime = date("Y-m", strtotime("-1 hour", $time));
        $startHourTime = $hourTime.':00:00';
        $endHourTime = date('Y-m-d H', $time).':00:00';
        $startDayTime = $dayTime.' 00:00:00';
        $endDayTime = date("Y-m-d", strtotime("+1 day", $time-3600)).' 00:00:00';
        $startMonthTime = $monthTime.'-01 00:00:00';
        $endMonthTime = date("Y-m", strtotime("+1 month", $time-3600)).'-01 00:00:00';
/*        echo $startHourTime;
        echo "\n";
        echo $endHourTime;
        echo "\n";
        echo $startDayTime;
        echo "\n";
        echo $endDayTime;
        echo "\n";
        echo $startMonthTime;
        echo "\n";
        echo $endMonthTime;
        echo "\n";
        exit;*/

        //查询所有的中继信息
        $winTrunkName = $this->getContainer()->get('doctrine')
            ->getRepository(WinTrunkName::class);
        $query = $winTrunkName->createQueryBuilder('q')
            ->getQuery();
        $result = $query->getResult();
        $trunkNames = array();
        foreach ($result as $key => $val) {
            $trunkNames[$val->getTrunkName()]['showName'] = $val->getShowName();
            $trunkNames[$val->getTrunkName()]['id'] = $val->getId();
        }

        //统计小时数据
        $winTrunkMonitorHour = $this->getContainer()->get('doctrine')
            ->getRepository(WinTrunkMonitorHour::class);
        $query = $winTrunkMonitorHour->createQueryBuilder('p')
            ->select('count(p)')
            ->where('p.time = :time')
            ->setParameter('time', $hourTime)
            ->getQuery();
        //表中没有上个小时的数据 就统计
        if ($query->getSingleScalarResult() == 0) {
            $this->hourStatisticsTrunk($trunkNames, $hourTime, $startHourTime, $endHourTime);
        }

        //统计天数据
        $this->dayStatisticsTrunk($trunkNames, $dayTime, $startDayTime, $endDayTime);

        //统计月数据
        $this->monthStatisticsTrunk($trunkNames, $monthTime, $startMonthTime, $endMonthTime);
    }

    /**
     * 按小时统计数据
     * @param array $trunkNames
     * @param string $hourTime
     * @param string $startTime
     * @param string $endTime
     */
    protected function hourStatisticsTrunk($trunkNames, $hourTime, $startTime, $endTime)
    {
        //es查询
        $esCondition = array(
            'fixup' => array(
                'index' => 'ccodcdr',
                'type' => "win_cdr_trunk",
            ),
            'term' => array(
                'time_start' => array('type' => 'range', 'value1' => ($startTime),'value2' => ($endTime), 'field' => 'time_start', 'operation1' => 'gte','operation2' => 'lt'),
            ),
            'size' => 0,
            'aggs'=>array(
                'trunk_grp'=>array(
                    'terms'=>array(
                        'field'=>'trunk_grp',
                    ),
                    'aggs'=>array(
                        'call_result'=>array(
                            'terms'=>array(
                                'field' => 'call_result',
                            ),
                        ),
                        'dur_conn' => array(
                            'sum' => array(
                                'field' => 'dur_conn',
                            ),
                        ),
                    ),
                )
            )
        );
        $data = $this->container->get('common_record')->searchData($esCondition);
        if ($data['code'] != 200) {
            $this->logger->error(sprintf("运维系统统计进程查询ES失败，返回【%s】", json_encode($data)));
            return;
        }
        //获取doctrine对象
        $em = $this->getContainer()->get('doctrine')->getManager();
        try{
            $em->getConnection()->beginTransaction(); // 开启一个事务
            foreach ($data['data']['aggregations']['trunk_grp']['buckets'] as $key => $val) {
                $connNum = 0;
                foreach ($val['call_result']['buckets'] as $k => $v) {
                    if ($v['key'] == 0) {
                        $connNum = $v['doc_count'];
                    }
                }
                $docCount = $val['doc_count'] ?? 0;
                $connNumRate = empty($val['doc_count']) ? '0%' : round($connNum/$val['doc_count']*100, 2).'%';
                $avgConnSecs = empty($connNum) ? 0 : round($val['dur_conn']['value']/$connNum, 2);
                $winTrunkMonitorHour = new WinTrunkMonitorHour();
                $winTrunkMonitorHour->setTrunkName($val['key'])
                    ->setCallNum($docCount)
                    ->setConnSecs($val['dur_conn']['value'])
                    ->setConnNum($connNum)
                    ->setTrunkId(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['id'] : '')
                    ->setShowName(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['showName'] : '')
                    ->setConnNumRate($connNumRate)
                    ->setTime($hourTime)
                    ->setAvgConnSecs($avgConnSecs);
                $em->persist($winTrunkMonitorHour);
                $em->flush();
            }
            $em->getConnection()->commit();
        } catch (\Exception $e) {
            $em->getConnection()->rollback();
            $this->logger->error(sprintf("按小时统计插入数据库失败，报错信息【%s】", $e->getMessage()));
        }
    }

    /**
     * 按天统计数据
     * @param array $trunkNames
     * @param string $dayTime
     * @param string $startTime
     * @param string $endTime
     */
    protected function dayStatisticsTrunk($trunkNames, $dayTime, $startTime, $endTime)
    {
        //es查询
        $esCondition = array(
            'fixup' => array(
                'index' => 'ccodcdr',
                'type' => "win_cdr_trunk",
            ),
            'term' => array(
                'time_start' => array('type' => 'range', 'value1' => ($startTime),'value2' => ($endTime), 'field' => 'time_start', 'operation1' => 'gte','operation2' => 'lt'),
            ),
            'size' => 0,
            'aggs'=>array(
                'trunk_grp'=>array(
                    'terms'=>array(
                        'field'=>'trunk_grp',
                    ),
                    'aggs'=>array(
                        'call_result'=>array(
                            'terms'=>array(
                                'field' => 'call_result',
                            ),
                        ),
                        'dur_conn' => array(
                            'sum' => array(
                                'field' => 'dur_conn',
                            ),
                        ),
                    ),
                )
            )
        );
        $data = $this->container->get('common_record')->searchData($esCondition);
        if ($data['code'] != 200) {
            $this->logger->error(sprintf("运维系统统计进程查询ES失败，返回【%s】", json_encode($data)));
            return;
        }
        //获取doctrine对象
        $em = $this->getContainer()->get('doctrine')->getManager();
        try{
            $em->getConnection()->beginTransaction(); // 开启一个事务
            foreach ($data['data']['aggregations']['trunk_grp']['buckets'] as $key => $val) {
                $connNum = 0;
                foreach ($val['call_result']['buckets'] as $k => $v) {
                    if ($v['key'] == 0) {
                        $connNum = $v['doc_count'];
                    }
                }
                $docCount = $val['doc_count'] ?? 0;
                $connNumRate = empty($val['doc_count']) ? '0%' : round($connNum/$val['doc_count']*100, 2).'%';
                $avgConnSecs = empty($connNum) ? 0 : round($val['dur_conn']['value']/$connNum, 2);
                //查看这条数据是否存在
                $winTrunkMonitorDay = $this->getContainer()->get('doctrine')
                    ->getRepository(WinTrunkMonitorDay::class);
                $query = $winTrunkMonitorDay->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.time = :time and p.trunkName = :trunkName')
                    ->setParameters(array('time' => $dayTime, 'trunkName' => $val['key']))
                    ->getQuery();
                //表中有没有要统计的数据 判断添加还是修改
                if ($query->getSingleScalarResult() > 0) {
                    $winTrunkMonitorDay = $this->getContainer()->get('doctrine')
                        ->getRepository(WinTrunkMonitorDay::class);
                    $winTrunkMonitorDay->findOneBy(array('time' => $dayTime, 'trunkName' => $val['key']))
                        ->setCallNum($docCount)
                        ->setConnSecs($val['dur_conn']['value'])
                        ->setConnNum($connNum)
                        ->setTrunkId(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['id'] : '')
                        ->setShowName(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['showName'] : '')
                        ->setConnNumRate($connNumRate)
                        ->setAvgConnSecs($avgConnSecs);
                    $em->flush();
                } else {
                    $winTrunkMonitorDay = new WinTrunkMonitorDay();
                    $winTrunkMonitorDay->setTrunkName($val['key'])
                    ->setCallNum($docCount)
                    ->setConnSecs($val['dur_conn']['value'])
                    ->setConnNum($connNum)
                    ->setTrunkId(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['id'] : '')
                    ->setShowName(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['showName'] : '')
                    ->setConnNumRate($connNumRate)
                    ->setTime($dayTime)
                    ->setAvgConnSecs($avgConnSecs);
                    $em->persist($winTrunkMonitorDay);
                    $em->flush();
                }
            }
            $em->getConnection()->commit();
        } catch (\Exception $e) {
            $em->getConnection()->rollback();
            $this->logger->error(sprintf("按天统计插入数据库失败，报错信息【%s】", $e->getMessage()));
        }
    }

    /**
     * 按月统计数据
     * @param array $trunkNames
     * @param string $monthTime
     * @param string $startTime
     * @param string $endTime
     */
    protected function monthStatisticsTrunk($trunkNames, $monthTime, $startTime, $endTime)
    {
        //es查询
        $esCondition = array(
            'fixup' => array(
                'index' => 'ccodcdr',
                'type' => "win_cdr_trunk",
            ),
            'term' => array(
                'time_start' => array('type' => 'range', 'value1' => ($startTime),'value2' => ($endTime), 'field' => 'time_start', 'operation1' => 'gte','operation2' => 'lt'),
            ),
            'size' => 0,
            'aggs'=>array(
                'trunk_grp'=>array(
                    'terms'=>array(
                        'field'=>'trunk_grp',
                    ),
                    'aggs'=>array(
                        'call_result'=>array(
                            'terms'=>array(
                                'field' => 'call_result',
                            ),
                        ),
                        'dur_conn' => array(
                            'sum' => array(
                                'field' => 'dur_conn',
                            ),
                        ),
                    ),
                )
            )
        );
        $data = $this->container->get('common_record')->searchData($esCondition);
        if ($data['code'] != 200) {
            $this->logger->error(sprintf("运维系统统计进程查询ES失败，返回【%s】", json_encode($data)));
            return;
        }
        //获取doctrine对象
        $em = $this->getContainer()->get('doctrine')->getManager();
        try{
            $em->getConnection()->beginTransaction(); // 开启一个事务
            foreach ($data['data']['aggregations']['trunk_grp']['buckets'] as $key => $val) {
                $connNum = 0;
                foreach ($val['call_result']['buckets'] as $k => $v) {
                    if ($v['key'] == 0) {
                        $connNum = $v['doc_count'];
                    }
                }
                $docCount = $val['doc_count'] ?? 0;
                $connNumRate = empty($val['doc_count']) ? '0%' : round($connNum/$val['doc_count']*100, 2).'%';
                $avgConnSecs = empty($connNum) ? 0 : round($val['dur_conn']['value']/$connNum, 2);
                //查看这条数据是否存在
                $winTrunkMonitorMonth = $this->getContainer()->get('doctrine')
                    ->getRepository(WinTrunkMonitorMonth::class);
                $query = $winTrunkMonitorMonth->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.time = :time and p.trunkName = :trunkName')
                    ->setParameters(array('time' => $monthTime, 'trunkName' => $val['key']))
                    ->getQuery();
                //表中有没有要统计的数据 判断添加还是修改
                if ($query->getSingleScalarResult() > 0) {
                    $winTrunkMonitorMonth = $this->getContainer()->get('doctrine')
                        ->getRepository(WinTrunkMonitorMonth::class);
                    $winTrunkMonitorMonth->findOneBy(array('time' => $monthTime, 'trunkName' => $val['key']))
                        ->setCallNum($docCount)
                        ->setConnSecs($val['dur_conn']['value'])
                        ->setConnNum($connNum)
                        ->setTrunkId(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['id'] : '')
                        ->setShowName(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['showName'] : '')
                        ->setConnNumRate($connNumRate)
                        ->setAvgConnSecs($avgConnSecs);
                    $em->flush();
                } else {
                    $winTrunkMonitorMonth = new WinTrunkMonitorMonth();
                    $winTrunkMonitorMonth->setTrunkName($val['key'])
                        ->setCallNum($docCount)
                        ->setConnSecs($val['dur_conn']['value'])
                        ->setConnNum($connNum)
                        ->setTrunkId(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['id'] : '')
                        ->setShowName(isset($trunkNames[$val['key']]) ? $trunkNames[$val['key']]['showName'] : '')
                        ->setConnNumRate($connNumRate)
                        ->setTime($monthTime)
                        ->setAvgConnSecs($avgConnSecs);
                    $em->persist($winTrunkMonitorMonth);
                    $em->flush();
                }
            }
            $em->getConnection()->commit();
        } catch (\Exception $e) {
            $em->getConnection()->rollback();
            $this->logger->error(sprintf("按月统计插入数据库失败，报错信息【%s】", $e->getMessage()));
        }
    }
}
